package org.xxpay.pay.channel.ysepay;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.exception.ServiceException;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.constant.RetEnum;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.PayDivisionRecord;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.core.entity.PayPassageAccount;
import org.xxpay.pay.channel.DivisionNotifyInterface;
import org.xxpay.pay.channel.PayConfig;
import org.xxpay.pay.channel.ysepay.util.SignUtils;
import org.xxpay.pay.service.CommonService;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @Author terrfly
 * @Date 2019/2/21 21:58
 * @Description 分账接口
 **/

@Service
public class YsepayDivisionNotifyService implements DivisionNotifyInterface {

    private static final MyLog logger = MyLog.getLog(YsepayDivisionNotifyService.class);

    @Autowired
    private CommonService commonService;

    @Autowired
    public PayConfig payConfig;

    /**
     * 获取三方支付配置信息
     * 如果是平台账户,则使用平台对应的配置,否则使用商户自己配置的渠道
     * @param payOrder
     * @return
     */
    private String getPayParam(PayOrder payOrder) {
        String payParam = "";
        PayPassageAccount payPassageAccount = commonService.payPassageAccountService.findById(payOrder.getPassageAccountId());
        if(payPassageAccount != null && payPassageAccount.getStatus() == MchConstant.PUB_YES) {
            payParam = payPassageAccount.getParam();
        }
        if(StringUtils.isBlank(payParam)) {
            throw new ServiceException(RetEnum.RET_MGR_PAY_PASSAGE_ACCOUNT_NOT_EXIST);
        }
        return payParam;
    }

    private String getChannelName() {
        return YsepayConfig.CHANNEL_NAME_YSEPAY;
    }



    public JSONObject doNotify(Object notifyData){

        JSONObject retObj = new JSONObject();
        try {
            String logPrefix = "【处理银盛分账回调】";
            logger.info("====== 开始处理银盛分账回调通知 ======");
            HttpServletRequest request = (HttpServletRequest) notifyData;
            Map<String, String> resParams = buildNotifyData(request);  //将参数转换为map格式
            logger.info("{} 分账异步通知参数： {}", logPrefix, resParams);

            if(resParams == null || resParams.isEmpty()) {
                throw new Exception("reqParams is null or empty");
            }

            String payOrderId = resParams.get("out_trade_no");
            PayOrder payOrder = commonService.payOrderService.findByPayOrderId(payOrderId);
            if(payOrder == null){
                throw new Exception("订单为查询失败！");
            }

            YsepayConfig ysepayConfig = new YsepayConfig(getPayParam(payOrder));  //获取银盛配置信息

            //分账用户的银盛公钥文件
            String publicCerFilePath = payConfig.getCertRootPath() + File.separator + getChannelName() + File.separator + ysepayConfig.getDivisionPublicCerPath();

            //验签
            boolean isTrue = SignUtils.rsaCheckContent(publicCerFilePath, resParams, resParams.get("sign"));
            if(!isTrue){  //验签失败
                throw new Exception("验签失败！");
            }

            logger.info("{}验证支付通知数据及签名通过", logPrefix);
            String divisionStatusCode = resParams.get("division_status_code");		// 分账状态

            //判断分账状态 处理业务
            if("0000".equals(divisionStatusCode) || "01".equals(divisionStatusCode) || "02".equals(divisionStatusCode) ){  //分账中

                PayDivisionRecord updateRecord = new PayDivisionRecord();
                updateRecord.setStatus(MchConstant.DIVISION_STATUS_ING);
                updateRecord.setLastNotifyTime(new Date());
                commonService.payDivisionRecordService.updateByOrderId(payOrderId, updateRecord);

                retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_SUCCESS);
                return retObj;
            }

            else if("00".equals(divisionStatusCode) ){   //成功
                PayDivisionRecord updateRecord = new PayDivisionRecord();
                updateRecord.setStatus(MchConstant.DIVISION_STATUS_SUCCESS);
                updateRecord.setLastNotifyTime(new Date());
                commonService.payDivisionRecordService.updateByOrderId(payOrderId, updateRecord);

                retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_SUCCESS);
                return retObj;
            }
            else if("99".equals(divisionStatusCode) ){  //失败
                PayDivisionRecord updateRecord = new PayDivisionRecord();
                updateRecord.setStatus(MchConstant.DIVISION_STATUS_ERROR);
                updateRecord.setLastNotifyTime(new Date());
                updateRecord.setChannelErrorMsg(resParams.get("note"));
                commonService.payDivisionRecordService.updateByOrderId(payOrderId, updateRecord);

                retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_SUCCESS);
                return retObj;
            }else{   //未知状态
                logger.error("分账异步接口，返回状态未知，无法继续处理。divisionStatusCode={} ",divisionStatusCode);
                retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_FAIL);
                return retObj;
            }

        } catch (Exception e) {
            logger.error("ysepay notify error: ", e);
            retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_FAIL);
            return retObj;
        }
    }


    //将请求参数转换为 map格式
    public Map buildNotifyData(HttpServletRequest request) {
        Map<String,String> params = new HashMap<>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        return params;
    }






}
